package demo1

import (
	"fmt"
	"strings"
	"sync"
)

// 整合设计模式练习

// 工厂设计模式 (抽象工厂设计模式)

type cook interface{
	Cook()
}

type vagetable struct{}

func NewVegetable() *vagetable{
	return &vagetable{}
}

func (v *vagetable)Cook(){
	fmt.Println("做菜")
}

type food struct{}

func NewFood() *food{
	return &food{}
}

func (f *food)Cooke(){
	fmt.Println("做饭")
}
// 工厂
type Home struct{
	factory cook
}
// 生产不同的食物
func NewHome(cook cook)*Home{
	return &Home{
		factory: cook,
	}
}

// 抽象工厂的话，把home结构体变成接口，然后工厂再抽象实例化
func(h *Home)Cook(){
	h.factory.Cook()
}
// ------------------------------------------------------------------------
// 外观设计模式

type fadongji struct{}
func NewFadongji() *fadongji{
	return &fadongji{}
}
func (f *fadongji)Fadong(){
	fmt.Println("发动")
}

type liheqi struct{}
func Newliheqi() *liheqi{
	return &liheqi{}
}
func (l *liheqi)ZhiDong(){
	fmt.Println("制动")
}


type youmen struct{}
func NewYoumen() *youmen{
	return &youmen{}
}
func (y *youmen)Run(){
	fmt.Println("run")
}

type car struct { 
  fadongji
  liheqi
  youmen
}

func NewCar() *car{
	return &car{
		NewFadongji(),
		Newliheqi(),
		NewYoumen(),
	}
}
// 对外暴露的方法
func (c *car) Run(){
	c.fadongji.Fadong()
	c.liheqi.ZhiDong()
	c.youmen.Run()
}

// 建造者设计模式

type builder interface{
	Build()
}

type construct struct{
	build builder
}

func NewConstruct(b builder) *construct{
	return &construct{
		build: b,
	}
}

// 分块调用
func (c *construct)bulit(){
	c.build.Build()
}

type executor  struct { 
   name string
}

func NewExecutor() *executor{
	return &executor{}
}

// 多个业务逻辑模块
func (e *executor)Build(){
	e.name = "haha"
}

// 对结果包装
type Result  struct { 
  result  string
}

func (e *executor)GetResult() *Result{
	return &Result{
		result: e.name,
	}
}

// 桥接设计模式
type bridger interface{
	Cross()
}

type wood  struct { 
  name string
}
func NewWood(name string) *wood{
	return &wood{
		name: name,
	}
}
func (w *wood)Cross(){
	fmt.Println(w.name)
}

type nail struct{
	name string
}
func NewNail(name string) *nail{
	return &nail{
		name: name,
	}
}
func (n *nail)Cross(){
	fmt.Println(n.name)
}

type connection struct{
	bridge []bridger
}
func NewConnection() *connection{
	return &connection{
		bridge: make([]bridger),
	}
}


func(c *connection) Cross(){
	// 贯穿两个方法do-somethings
}

// 命令设计模式
type Command interface{
	Execute()
}

type StartBorad struct{
	mb *MotherBorad
}

func NewBorad(mb *MotherBorad) *StartBorad{
	return &StartBorad{
		mb: mb,
	}
}

func (b *StartBorad)Execute(){
	b.mb.Start()
}
type StopBord struct { 
   mb *MotherBorad
}
func NewStopBord(mb *MotherBorad) *StopBord{
	return &StopBord{
		mb: mb,
	}
}

func (s *StopBord)Execute(){
	s.mb.Stop()
}

type MotherBorad struct{}
func NewMotherBorad() *MotherBorad{
	return &MotherBorad{}
}
func (m *MotherBorad)Start(){
	fmt.Println("start")
}
func (m *MotherBorad)Stop(){
	fmt.Println("stop")
}

// 命令统计位置
type Box struct{
	button1 Command,
	button2 Command,
}

func NewBox(button1, button2 Command)*Box{
	return &Box{
		button1: button1,
		button2: button2,
	}
}
func (b *Box)Execute(){
	b.button1.Execute()
	b.button2.Execute()
}


// 原型设计模式
type Cloneable interface{
	Clone() Cloneable
}

type PrototypeManager struct{
	prototypes map[string]Cloneable
}

func NewPrototypeManager() *PrototypeManager{
	return &PrototypeManager{
		prototypes: make(map[string]Cloneable),
	}
}

func (p *PrototypeManager)Get(name string) Cloneable{
	return p.prototypes[name]
}
func (p *PrototypeManager)Set(name string, clone Cloneable){
	p.prototypes[name] = clone
}
// 适配设计模式 
type Target interface{
	Request() string
}
//  两个不同的配置转换成一个可以共用的配置
type Adaptee interface{
	SpecificalRequest() string
}

type adapter struct{
	name string
}
func NewAdapter(name string) *adapter{
	return &adapter{
		name: name,
	}
}
func (a *adapter)SpecificalRequest() string{
	return a.name
}

type targeter struct{
	Adapter Adaptee
}
// 不同的对象都行满足了拓展性 |需要修改上层的业务，只需要下层做拓展
func NewTargeter(adaptee Adaptee) *targeter{
	return &targeter{
		Adapter: adaptee,
	}
}
func (t *targeter)Request()string{
	// 适配器转换成可以调用的方法
	return t.Adapter.SpecificalRequest()
}


// 单利设计模式
type Singleton struct{}
var once sync.Once
var singleton *Singleton

func GetInstance() *Singleton{
	once.Do(func(){
		singleton = &Singleton{}
	})
	return singleton
}

// 代理设计模式/
type Subject interface{
	Do()
}
// 原来的方法
type RealSubject struct{}

func NewRealSubject() *RealSubject{
	return &RealSubject{}
}
func (r *RealSubject)Do(){
	fmt.Println("原来的方法，原来的配方")
}

// 被代理使用的 类似装饰
type Proxy struct{
	RealSubject
}
func NewProxy() *Proxy{
	return &Proxy{}
}
func (p *Proxy)Do(){
	fmt.Println("配方之前可以做点啥")
	p.RealSubject.Do()
	fmt.Println("配方之后又可以做点啥")
}

// 中介者设计模式  将原有的结构体进行拆分成简单的模块并且减少耦合
type CDDriver struct{
	Data string
}
func (c *CDDriver) ReadData(){
	c.Data = "music,image"
	fmt.Println("CDDIrver",c.Data)
	GetMediatorInstanc().changed(c)
}

type CPU struct{
	Vedio string
	Sound string
}

func (c *CPU)Process(data string){
	sp := strings.Split(data,",")
	c.Vedio = sp[0]
	c.Sound = sp[1]
	GetMediatorInstanc().changed(c)
}

type SoundCard struct{
	Data string
}

func (s *SoundCard) Play(data string){
	s.Data = data
	GetMediatorInstanc().changed(s)
}

type VedioCard struct{
	Data string
}
func (s *VedioCard) DisPlay(data string){
	s.Data = data
	GetMediatorInstanc().changed(s)
}

// 有一定的执行顺序 如果这样的写法
type mediator struct{
	cd *CDDriver
	cpu *CPU
	v   *VedioCard
	s   *SoundCard
}

var mediator *mediator

// 涉及到的单利模式
func GetMediatorInstanc() *mediator{
	if mediator == nil {
		mediator = &mediator{}
	}
	return mediator
}

func (m *mediator)changed(inst interface{}){

	switch ins:=inst.(type) {
	case *CDDriver:
		// ---
		m.cpu.Process(ins.Data)
	case *CPU:
		// ---
		m.s.Play(ins.Sound)
		m.v.DisPlay(ins.Vedio)
	}
}